package com.hl.socket;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;
import com.hl.util.AnalysisStr;
import com.hl.util.BaseDao;
import com.hl.util.CodeAttribute;
import com.hl.util.DBHelper;

/**
 * 接收指令类
 * @author Administrator
 *
 */
public class SocketInput implements Runnable{
	private Socket socket;
	private Map<String,CodeAttribute> map;
	//查询数据库
	private DBHelper dbHelper = new DBHelper();
	private Connection connection = null;

	public SocketInput(Socket socket,Map<String,CodeAttribute> map) {
		this.socket = socket;
		this.map = map;
	}
	@Override
	public void run() {
		BufferedReader bff = null;
		AnalysisStr analy = new AnalysisStr();  //创建解析指令类
		CodeAttribute code = null;
		try {
			// 从客户端获取信息
			bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			// 读取发来服务器信息
			String line = null;
			// 循环一直接收当前socket发来的消息
			String info = null;
			while ((info = bff.readLine()) != null) {
				try {
					code = analy.analy(info,code);  //解析
					if(code == null) {continue;}
					System.out.println("客户端唯一编号为:"+code.getClientOnlyId() );
					code.setSocket(socket);  //把socket保存
					code.setConnectionStatus(true); //客户端连接成功,设置状态
					map.put(code.getClientOnlyId(), code);//把客户端信息保存到map
					processingInstruction(code); //开始处理客户端指令
				} catch (Exception e) {
					System.out.println("服务器接收指令线程出错,字符串读取出错..." + e);
				}
			}
			System.out.println("===================" + code.getClientOnlyId() + " 的客户端已掉线,服务器移除连接,更新在线状态 ===================");
			updateStatu(code.getClientOnlyId(),0);  //更新数据库在线状态
			map.remove(code.getClientOnlyId());//移除客户端信息
		} catch (Exception e) {
			System.out.println("客户端关闭了连接...读取客户端数据异常.");
			if(socket != null && socketClose(socket,bff)) {
				System.out.println("关闭连接成功---退出循环");
				map.remove(code.getClientOnlyId()); //移除客户端
				return;
			}
			System.out.println("关闭失败!");
		}
	}

	/**
	 * 更新在线状态
	 * @param code
	 */
	public void updateStatu(String clientOnlyId,int statu) {
		int res = -1;
		try {
			DBHelper dbHelper = new DBHelper();
			String sql = "UPDATE `wifi` SET `statu` = ?,updateTime = ? WHERE `clientOnlyId` = ?";
			connection = dbHelper.getConnection();
			BaseDao dao = new BaseDao(connection);
			res = dao.executeUpdate(sql,statu,new Date(),clientOnlyId);
			System.out.println("更新客户端" + (res > 0 ? "成功":"失败"));
		} catch (Exception e) {
			System.out.println("更新失败 客户端唯一id为: " + clientOnlyId);
		}
	}

	/**
	 * 处理指令
	 */
	public void processingInstruction(CodeAttribute code) {
		if("0000".equalsIgnoreCase(code.getClientTypeNumber())) {
			//wifi模块连接指令
			System.err.println("WIFI端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
		}else if("1111".equalsIgnoreCase(code.getClientTypeNumber())) {
			androidSend(code);  //安卓发送指令
		}else if("2222".equalsIgnoreCase(code.getClientTypeNumber())) {
			//心跳代码
		}else if("3333".equalsIgnoreCase(code.getClientTypeNumber())) {
			//wifi模块执行成功指令的代码
			System.out.println("进入反馈方法");
			boolean flag  = feedbackResult(code);
			System.out.println("获取反馈结果"+flag);

		}else {
			System.out.println("指令错误!");
		}
	}

	/**
	 * 安卓发送数据
	 * @param code
	 * @return
	 */
	public boolean androidSend(CodeAttribute code) {
		//安卓端
		System.err.println("安卓端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
		if(code.getInstructionLength() == 4) {
			new Thread() {  //连接成功后发送反馈信息
				@Override
				public void run() {
					try {
						String data = "连接成功\n";
						OutputStream outputStream = code.getSocket().getOutputStream();
						outputStream.write(data.getBytes("utf-8"));
						outputStream.flush();
					} catch (Exception e) {
						System.out.println("给 "+code.getClientOnlyId() + " 反馈信息发送失败" + e);
					}
				}
			}.start();
		}
		if(code.getSendOnlyId() != null) {  //判断安卓端是否发送指令
			//获取要发送给那个WIFI模块
			CodeAttribute codes = getMapData(map, code);
			Socket socket  = codes.getSocket(); //获取wifi客户端的socket流
			OutputStream out = null;
			try {
				if(socket == null) {System.out.println("socket为空...发送失败");return false;}
				out = socket.getOutputStream();
				String data = code.getSendData();  //获取发送的数据
				data += "\n";
				System.err.println("发送的指令为: "+data);
				out.write(data.getBytes("utf-8"));
				out.flush();
				boolean flag = udpateData(map,code);
				System.out.println("更新标识成功..."+ flag);
			} catch (IOException e) {
				udpateData(map,code);
				System.out.println("出现异常,发送失败..." + e);
				socketClose(socket,out);  //关闭socket
				map.remove(code.getClientOnlyId());
			}
		}
		return true;
	}

	/**
	 * wifi模块处理完指令后 发送的反馈结果
	 */
	public boolean feedbackResult(CodeAttribute code) {
		Socket socket = null;
		boolean flag = false;
		OutputStream outputStream =	null;
		//获取要发送给那个客户端(安卓)
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			if(entries.getKey().equals(code.getSendOnlyId())) {
				System.out.println("反馈数据发送给 :" + code.getSendOnlyId());
				socket  = entries.getValue().getSocket();  //获取安卓端socket流
				flag  = entries.getValue().getSuccess();
				break;
			}
		}
		try {
			if(socket == null) {return false;}
			String data = code.getSendData();
			data += "\n";
			outputStream = socket.getOutputStream();
			outputStream.write(data.getBytes("utf-8"));
			outputStream.flush();
		} catch (IOException e) {
			System.out.println("反馈信息发送失败" + e);
			socketClose(socket,outputStream);
			return false;
		}
		return true;
	}


	/**
	 * 关闭socket
	 * @param socket
	 */
	public boolean socketClose(Closeable... targets) {
		for(Closeable target:targets) {
			try {
				if(null!=target) {
					target.close();
					System.out.println("接收指令类--->关闭成功...");
				}
			}catch(Exception e) {
				System.out.println("关闭连接失败!");
				return false;
			}
		}
		return true;
	}

	/**
	 * 更新map数据
	 * @param map
	 * @param code
	 */
	public boolean udpateData(Map<String,CodeAttribute> map,CodeAttribute code) {
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			if(entries.getKey().equals(code.getSendOnlyId())) {
				entries.getValue().setSuccess(true);
				return true;
			}
		}
		return false;
	}
	/**
	 * 获取map客户端编号
	 * @param map
	 * @param code
	 */
	public CodeAttribute getMapData(Map<String,CodeAttribute> map,CodeAttribute code) {
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			if(entries.getKey().equals(code.getSendOnlyId())) {  
				return entries.getValue();
			}
		}
		return null;
	}
}
/**
 * 发送心跳类
 * @author Administrator
 *
 */
class Heartbeat implements Runnable{
	private Timer timer = new Timer(); //定时操作类
	private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//设置日期格式
	private Integer seconds = 30000; //毫秒 120000
	private Socket socket = null;
	private Map<String,CodeAttribute> map;
	private OutputStream output;
	private String heartbeat = "P\n";  //心跳码
	//查询数据库
	DBHelper dbHelper = new DBHelper();
	Connection connection = null;

	public Heartbeat(Map<String, CodeAttribute> map) {
		this.map = map;
	}
	@Override
	public void run() {
		staticTimer();
	}

	public void staticTimer() {
		timer.schedule(new TimerTask(){
			@Override
			public void run() {
				if(map.size() != 0) {
					for (Entry<String, CodeAttribute> entries : map.entrySet()) {
						try {
							socket = entries.getValue().getSocket();
							if(socket != null) {
								String data = df.format(new Date());
								System.out.println(entries.getKey() + "状态 --->" + (entries.getValue().isConnectionStatus() ? "在线":"客户端断开了连接"));
								System.out.println(entries.getValue().hashCode() +" "+ "********服务器给编号为：" + entries.getKey() + " 发送心跳*******时间: " + data);
								//socket.sendUrgentData(80);
								socket.getOutputStream().write(heartbeat.getBytes("utf-8"));
								socket.getOutputStream().flush();
							}
						} catch (Exception e) {
							boolean flag = socketClose(socket,output); //关闭连接
							entries.getValue().setConnectionStatus(false);
							map.remove(entries.getKey()); //移除socket
							System.out.println("给 [ " +entries.getKey()+ "] 发送心跳失败 ! " + " " +" 服务器主动关闭socket连接 " + (flag?"成功":"失败"));
							updateStatu(entries.getValue().getClientOnlyId(),0);  //更新在线状态
						}
					}
					System.out.println("客户端数量为 :" + map.size());
				}
			}},1000, seconds);
	}
	/**
	 * 关闭socket
	 * @param socket
	 */
	public boolean socketClose(Closeable... targets) {
		for(Closeable target:targets) {
			try {
				if(null!=target) {
					target.close();
					System.out.println("定时类--->关闭成功...");
				}
			}catch(Exception e) {
				System.out.println("关闭连接失败!");
				return false;
			}
		}
		return true;
	}

	/**
	 * 更新在线状态
	 * @param code
	 */
	public void updateStatu(String clientOnlyId,int statu) {
		int res = -1;
		try {
			DBHelper dbHelper = new DBHelper();
			String sql = "UPDATE `wifi` SET `statu` = ?,updateTime = ? WHERE `clientOnlyId` = ?";
			connection = dbHelper.getConnection();
			BaseDao dao = new BaseDao(connection);
			res = dao.executeUpdate(sql,statu,new Date(),clientOnlyId);
			System.out.println("更新客户端" + (res > 0 ? "成功":"失败"));
		} catch (Exception e) {
			System.out.println("更新失败 客户端唯一id为: " + clientOnlyId);
		}
	}
}